package TouristManagementBO;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Locale;
import java.util.Properties;
import java.util.Random;

import TouristManagement.*;
import TouristManagementBO.Others.ServerNamingTouristImpl;

public class TouristClientTest {
	private TouristOffice leTouristOffice;
	private ArrayList<Site> lesSites = new ArrayList<Site>();
	private short touristCardNumber;
	private Site leSiteVisitActuel;
	private ServerNamingTourist leServerNamingTourist;
	
		
	public TouristClientTest() {		
		this.touristCardNumber = 0;
	}
	
	public void initServer(){
		this.connectToServerNamingTourist();
		this.connectToTouristOfficeServer();
		this.connectToSiteServers();
	}
	
	public void setTouristCardNumber(short i){
		this.touristCardNumber = i;
	}
	
	public void connectToServerNamingTourist(){
		//init VisitManagement server
		try {
			
	        String args[]=null;

			// Intialisation de l'orb
			org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args,null);

	        // Recuperation du naming service
	        org.omg.CosNaming.NamingContext nameRoot =
	        		org.omg.CosNaming.NamingContextHelper.narrow(orb.resolve_initial_references("NameService"));

	        // Construction du nom a rechercher
	        org.omg.CosNaming.NameComponent[] nameToFind = new org.omg.CosNaming.NameComponent[1];
	         nameToFind[0] = new org.omg.CosNaming.NameComponent("ServerNamingTourist","");

	        // Recherche aupres du naming service
	        org.omg.CORBA.Object distantServerNamingTourist = nameRoot.resolve(nameToFind);
	        
	        leServerNamingTourist = ServerNamingTouristHelper.narrow(distantServerNamingTourist);
	        
	        System.out.println("Tourist naming server connected.");
		}
		catch (Exception e) {
			e.printStackTrace();
		}		
	}	
	
	public void purchaseCard(){
		//saisir le nom
		System.out.print("Enter your name : ");
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		String nom = null;
		try {
			 nom = in.readLine();
		} catch (IOException e) {
			System.out.println("The name can not be null.");			
			System.out.println("Press Enter to continue");
			try{in.readLine();}
			catch(Exception e1){}
			this.afficherMenuAccueilTourist();
		}
				
		//identify the current date for start date   
        //TODO add the choice of start date
        Calendar cal = Calendar.getInstance(new Locale("fr", "fr"));  
        short day = (short) cal.get(Calendar.DAY_OF_MONTH);
        short year = (short) cal.get(Calendar.YEAR);  
        short month = (short) (cal.get(Calendar.MONTH)+1);
        DateV startDate = new DateV(year,month,day);
        
        //TODO choisir nb jour
        
        //identify the end date = start date + 1 month        
        month = (short) (cal.get(Calendar.MONTH)+2);
        DateV endDate = new DateV(year,month,day); 

        //purchase the card and save the card number
        touristCardNumber = leTouristOffice.purchaseCard(nom, startDate, endDate);  
        
        //redirection to main menu
        System.out.println("Card purchased.");
        System.out.println("Card number : "+touristCardNumber);
		System.out.println("Press Enter to continue");
		try {
			in.readLine();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		this.afficherMenuAccueilTourist();
		
	}
	
	@SuppressWarnings("deprecation")
	public void afficherMenuAccueilNonTourist(){
		//clear screen
		int n=0;
		do {
			for (int i = 0; i < 10; i++) {		
			   System.out.println();
			  }
			System.out.println("******************************************");
			System.out.println("WELCOME TO TOURIST MANAGEMENT APPLICATION");
			System.out.println("STATUS : NEW TOURIST");
			System.out.println("			MENU ");
			System.out.println("1. Purchase new card");
			System.out.println("2. Quit.");
			System.out.print("Enter your choice : ");
			BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
	        String choix = null;
			try {
				choix = in.readLine();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	        n = Integer.parseInt(choix); 
		}while (n!=1 && n!=2); 
		switch (n) {
			case 1: purchaseCard();
				break;
			case 2: Thread.currentThread().stop();
				break;
		}		
	}
	
	@SuppressWarnings("deprecation")
	public void afficherMenuAccueilTourist(){
		//clear screen
		int n=0;
		do {
			for (int i = 0; i < 10; i++) {		
			   System.out.println();
			  }
			System.out.println("******************************************");
			System.out.println("WELCOME TO TOURIST MANAGEMENT APPLICATION");
			System.out.println("TOURIST N�"+touristCardNumber);
			System.out.println("			MENU ");
			System.out.println("1. Check in a site.");
			System.out.println("2. Consult the list of sites.");
			System.out.println("3. Quit.");
			System.out.print("Please enter your choice: ");
			BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
	        String choix = null;
			try {
				choix = in.readLine();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	        n = Integer.parseInt(choix); 
		}while (n<1 && n>3); 
		switch (n) {			
			case 1: checkInSite();
				break;
			case 2: consultListeSites();
				break;
			case 3: Thread.currentThread().stop();
				break;
		}		
	}
	
	public void afficherMenuAccueil(){
		if (!leTouristOffice.existTourist(touristCardNumber)) this.afficherMenuAccueilNonTourist();
		else {
			//checking if the tourist is visiting a site
			this.leSiteVisitActuel = leTouristOffice.siteVisiting(touristCardNumber);
			if (this.leSiteVisitActuel!=null) this.afficherMenuAccueilTouristVisiting();			
			else this.afficherMenuAccueilTourist();
			}
	}

	public void afficherMenuAccueilTouristVisiting() {
		//clear screen
				int n=0;
				do {
					for (int i = 0; i < 10; i++) {		
					   System.out.println();
					  }
					System.out.println("******************************************");
					System.out.println("WELCOME TO TOURIST MANAGEMENT APPLICATION");
					System.out.println("TOURIST N°"+touristCardNumber);
					System.out.println("SITE ACTUEL : "+leSiteVisitActuel.getNomSite());
					System.out.println("			MENU ");
					System.out.println("1. Check out a site");
					System.out.println("2. Consult the list of sites.");
					System.out.print("Please enter your choice: ");
					BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
			        String choix = null;
					try {
						choix = in.readLine();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
			        n = Integer.parseInt(choix); 
				}while (n<1 && n>2); 
				switch (n) {
					case 1: checkOutSite();
						break;
					case 2: consultListeSites();
						break;
				}		
	}

	private void consultListeSites() {
		
		//create an random GPS
		
		//retourner un valeur random entre 0 et 100 (minutes)
		Random rd = new Random();
		int x = rd.nextInt(100)+1;
		int y = rd.nextInt(100)+1;
		CoordsGPS position = new CoordsGPS ((short)x,(short)y);
		System.out.println("Your current GPS position is (" + x + "," + y + ").");
		System.out.println("Asking the tourist office server...");
		InfoSite[] result = leTouristOffice.consultListeSites(touristCardNumber, position);
		//afficher la liste des sites		
		int n = 0;
		System.out.println("List of nearest not-visited sites : ");
		while (n<5 && result[n]!=null) {
			//on en prend que les sites non visités
			if (!result[n].visited) {
				System.out.println("*******************************");
				System.out.println("Nom site : " + result[n].siteName);
				System.out.println("Opening hour : " + result[n].openingHours.hour + "h"+ result[n].openingHours.minute + "m" + result[n].openingHours.seconde +"s");
				System.out.println("Closing hour : " + result[n].closingHours.hour + "h"+ result[n].closingHours.minute + "m" + result[n].closingHours.seconde +"s");
				System.out.println("Current number of visitors : " + result[n].currentNbVisitors);
				System.out.println("Max number of visitors : " + result[n].maxNbVisitors);
				//get info traffic
				System.out.println("Traffic time by : ");
				InfoTraffic[] infoTraffic = result[n].infosTraffic;
				for (InfoTraffic info:infoTraffic) {
					System.out.println("    - " + info.nameSystem + " : " + info.trafficTime + " min");
				}				
				System.out.println("*******************************");
			}
			n++;
		}
		System.out.println("Press Enter to continue");
		try{ 
			BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
			in.readLine(); }
		catch(Exception e){}
		this.afficherMenuAccueil();
	}
	
	public Advice adviceRequest() {		
		
        try {
			String avis = null;
			int i = -1; 
			{
				System.out.println("1.Not interesting");
				System.out.println("2.Marginal");
				System.out.println("3.Interesting");
				System.out.println("4.Worthly");
				System.out.println("5.Must visit");
				System.out.print("Please enter your advice (1-5) : ");
				BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
				avis = in.readLine();
				i = Integer.parseInt(avis);				 
			}while (i<1 && i>5);
			switch (i) {
				case 1: return Advice.NotInteresting;
				case 2: return Advice.Marginal;
				case 3: return Advice.Interesting;
				case 4: return Advice.Worthly;
				case 5: return Advice.MustVisit;	
				default : return null;
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;        
	}
	
	public void connectToTouristOfficeServer(){
		try {
			
			Properties props = new Properties();
	        props.put("org.omg.CORBA.ORBInitialPort", "2001");
	        props.put("org.omg.CORBA.ORBInitialHost", "127.0.0.1");
	        
	        String args[] = null;

			// Intialisation de l'orb
			org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args,null);

	        // Recuperation du naming service
	        org.omg.CosNaming.NamingContext nameRoot =
	        		org.omg.CosNaming.NamingContextHelper.narrow(orb.resolve_initial_references("NameService"));

	        // Construction du nom a rechercher
	        org.omg.CosNaming.NameComponent[] nameToFind = new org.omg.CosNaming.NameComponent[1];
	         nameToFind[0] = new org.omg.CosNaming.NameComponent(leServerNamingTourist.get_nomTouristOffice(),"");

	        // Recherche aupres du naming service
	        org.omg.CORBA.Object distantTouristOffice = nameRoot.resolve(nameToFind);
	        leTouristOffice = TouristOfficeHelper.narrow(distantTouristOffice);
	        System.out.println("OfficeTourist connected.");
		}
		catch (Exception e) {
			e.printStackTrace();
		}		
	}
	
	public void connectToSiteServers(){
		try {			
			
			short[] lesIdSites = leTouristOffice.getIdSite();
			
	        String args[] = null;

			// Intialisation de l'orb
			org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args,null);

	        // Recuperation du naming service
	        org.omg.CosNaming.NamingContext nameRoot =
	        		org.omg.CosNaming.NamingContextHelper.narrow(orb.resolve_initial_references("NameService"));
	        
	        //connect to sites
	        for (short i:lesIdSites){
		        // Construction du nom a rechercher
		        org.omg.CosNaming.NameComponent[] nameToFind = new org.omg.CosNaming.NameComponent[1];
		         nameToFind[0] = new org.omg.CosNaming.NameComponent(leServerNamingTourist.get_nomSites()[i-1],"");
	
		        // Recherche aupres du naming service
		        org.omg.CORBA.Object distantSite = nameRoot.resolve(nameToFind);
		        System.out.println("Site "+ leServerNamingTourist.get_nomSites()[i-1] + " connected, id "+i);
		        
		        lesSites.add(SiteHelper.narrow(distantSite));	 
	        }	        
		}
		catch (Exception e) {
			e.printStackTrace();
		}		
	}

	private void checkOutSite() {	
		//request the advice of the visitor
		Advice leAdvice = this.adviceRequest();
		if (leAdvice != null) {
			//check out the visitor and retrieve the VisitManagement object
			VisitManagement leVisitManagement = leSiteVisitActuel.checkOut(touristCardNumber);
			//add advice by using VisitManagement object		
			leVisitManagement.addAdvice(leSiteVisitActuel.idSite(), touristCardNumber, leAdvice);
			System.out.println("Check out OK.");
			leSiteVisitActuel = null;
		}
		else System.out.println("Error, check out is not OK.");
		//redirection to main menu
		System.out.println("Press Enter to continue");
		try{
			BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
			in.readLine(); 
		}
		catch(Exception e){}
		this.afficherMenuAccueilTourist();		
	}

	private void checkInSite() {			
		System.out.println("******************************************");
		System.out.println("WELCOME TO TOURIST MANAGEMENT APPLICATION");
		System.out.println("			CHECK-IN SITE ");
		//display sites	
		for (Site s:lesSites) System.out.println(s.idSite()+". "+s.getNomSite());
		System.out.println((lesSites.size()+1)+". Quit.");

        int n=0;
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        String choix = null;
		{
				
			System.out.print("Please enter your choice : ");
			
			try 
			{
				choix = in.readLine();
		        n = Integer.parseInt(choix); 
			} 
			catch (IOException e) 
			{
				e.printStackTrace();
			}
		} while (n<0 || n>lesSites.size()+1);
		
		if (n==lesSites.size()+1) Thread.currentThread().interrupt();
		else 
		{
			//if the tourist choose to visit a site
			for (Site s:lesSites) {
				//affect the site to site visit actual
				if (n==s.idSite()) {
					leSiteVisitActuel=s;					
				}
			}
			try 
			{
				System.out.println("Connecting to " + leSiteVisitActuel.getNomSite());
				leSiteVisitActuel.checkIn(touristCardNumber);
			} 
			catch (CheckInNotValid e) 
			{			
				System.out.println(e.cause);
				//redirection to main menu
				leSiteVisitActuel = null;
				System.out.println("Check in is not OK.");
				System.out.println("Press Enter to continue");
				try 
				{				
					in.readLine(); 
				} 
				catch (IOException e1) 
				{				
					e1.printStackTrace();
				}
				this.afficherMenuAccueil();
			}
			System.out.println("Check in OK.");
			System.out.println("Press Enter to continue");
			try
			{
				in.readLine();
			}
			catch(Exception e){}
			this.afficherMenuAccueil();
		}
	}

	public static void main(String args[]) {
		
		TouristClientTest t = new TouristClientTest();
		
		//connect to servers
		t.initServer();
		
		String choix="";
		int n = 0;
		
		{
			for (int i = 0; i < 10; i++) System.out.println();
			System.out.print("1. Purchase new card");
			System.out.print("2. Login");
			System.out.print("Please enter the tourist card number : ");
			BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
			try {
				choix = in.readLine();
				n = Integer.parseInt(choix);
			} catch (IOException e) {
				e.printStackTrace();
			}	        
		} while (n!=1 && n !=2);
		if (n==1) 
		{
			//purchase new card
			t.afficherMenuAccueilNonTourist();
		}
		if (n==2)
		{
			System.out.print("Please enter the tourist card number : ");
			BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
			short touristCardNumber=0;;
			try {
				choix = in.readLine();
				touristCardNumber = Short.parseShort(choix);
			} catch (IOException e) {
				e.printStackTrace();
			}	
			if (t.leTouristOffice.existTourist(touristCardNumber))
			
		}
		t.setTouristCardNumber(Short.parseShort(choix));
		
		t.afficherMenuAccueil();
		
        
	} // main

}
